package net.sk.china.city.talk.service.impl.wechat;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.sk.china.city.talk.constants.WeChatConstants;
import net.sk.china.city.talk.dao.wechat.TemplateMessageDao;
import net.sk.china.city.talk.model.system.SystemNotification;
import net.sk.china.city.talk.model.wechat.TemplateMessage;
import net.sk.china.city.talk.response.wechat.*;
import net.sk.china.city.talk.service.system.SystemNotificationService;
import net.sk.china.city.talk.service.wechat.TemplateMessageService;
import net.sk.china.city.talk.service.wechat.WechatNewService;
import net.sk.china.common.exception.TalkException;
import net.sk.china.common.utils.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * TemplateMessageServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * // | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
 * // +----------------------------------------------------------------------
 * // | Copyright (c) 2018-2024 聊来 All rights reserved.
 * // +----------------------------------------------------------------------
 * // | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">apache</a> )
 * // +----------------------------------------------------------------------
 * // | @Author: 聊来 <18970881148@qq.com>
 * // +----------------------------------------------------------------------
 * // | DateTime: 2024/6/3 17:27
 * // +----------------------------------------------------------------------
 */

@Service
public class TemplateMessageServiceImpl extends ServiceImpl<TemplateMessageDao, TemplateMessage> implements TemplateMessageService {

    private static final Logger logger = LoggerFactory.getLogger(TemplateMessageServiceImpl.class);

    @Resource
    private TemplateMessageDao dao;

    private final SystemNotificationService systemNotificationService;

    private final WechatNewService wechatNewService;

    private final RedisUtil redisUtil;

    public TemplateMessageServiceImpl(@Lazy SystemNotificationService systemNotificationService, WechatNewService wechatNewService, RedisUtil redisUtil) {
        this.systemNotificationService = systemNotificationService;
        this.wechatNewService = wechatNewService;
        this.redisUtil = redisUtil;
    }

    /**
     * 获取详情
     * @param id 数据ID
     * @return {@code TemplateMessage}
     */
    @Override
    public TemplateMessage info(Integer id) { return getById(id); }

    /**
     * 公众号模板消息同步
     * @return {@code boolean}
     */
    @Override
    public boolean wechatSync() {
        List<SystemNotification> notificationList = systemNotificationService.getListByWechat("public");
        List<Integer> wechatIdList = notificationList.stream().map(SystemNotification::getWechatId).collect(Collectors.toList());
        List<TemplateMessage> templateMessageList = getListByIdList(wechatIdList);
        if (CollUtil.isEmpty(templateMessageList)) {
            throw new TalkException("请先添加公众号模板消息");
        }

        // 获取公众平台所有的微信模板，删除之
        List<PublicTemplateResponse> templateVoList = wechatNewService.getPublicTemplateList();
        templateVoList.forEach(e -> wechatNewService.delPublicTemplate(e.getTemplate_id()));
        // 将现在的模板保存到公众平台
        templateMessageList.forEach(e -> {
            String templateId = wechatNewService.addPublicTemplate(e.getTempKey());
            e.setTempId(templateId);
        });
        return updateBatchById(templateMessageList);
    }

    /**
     * 小程序订阅消息同步
     * @return {@code boolean}
     */
    @Override
    public boolean routineSync() {
        List<SystemNotification> notificationList = systemNotificationService.getListByWechat("routine");
        List<Integer> routineIdList = notificationList.stream().map(SystemNotification::getRoutineId).collect(Collectors.toList());
        List<TemplateMessage> templateMessageList = getListByIdList(routineIdList);
        if (CollUtil.isEmpty(templateMessageList)) {
            throw new TalkException("请先配置小程序订阅消息");
        }
        // 获取当前帐号下的模板列表
        List<RoutineTemplateResponse> templateVoList = wechatNewService.getRoutineTemplateList();
        // 删除原有模板
        templateVoList.forEach(e -> wechatNewService.delRoutineTemplate(e.getPriTmplId()));
        // 将现在的模板保存到小程序平台
        templateMessageList.forEach(e -> {
            // 获取小程序平台上的标准模板
            List<RoutineTemplateKeyResponse> templateKeyVoList = wechatNewService.getRoutineTemplateByWechat(e.getTempKey());
            List<Integer> kidList = getRoutineKidList(e.getContent(), templateKeyVoList);
            String priTmplId = wechatNewService.addRoutineTemplate(e.getTempKey(), kidList);
            e.setTempId(priTmplId);
        });
        return updateBatchById(templateMessageList);
    }

    /**
     * 公众号消费队列消费
     */
    @Override
    public void consumePublic() {
        String redisKey = WeChatConstants.WE_CHAT_MESSAGE_KEY_PUBLIC;
        Long size = redisUtil.getListSize(redisKey);
        logger.info("TemplateMessageServiceImpl.consumePublic | size:" + size);
        if(size < 1){
            return;
        }
        for (int i = 0; i < size; i++) {
            //如果10秒钟拿不到一个数据，那么退出循环
            Object data = redisUtil.getRightPop(redisKey, 10L);
            if(null == data){
                continue;
            }
            try{
                TemplateMessageResponse templateMessage = JSONObject.toJavaObject(JSONObject.parseObject(data.toString()), TemplateMessageResponse.class);
                boolean result = wechatNewService.sendPublicTemplateMessage(templateMessage);
                if(!result){
                    redisUtil.lPush(redisKey, data);
                }
            }catch (Exception e){
                redisUtil.lPush(redisKey, data);
            }
        }
    }

    /**
     * 小程序消费队列消费
     */
    @Override
    public void consumeProgram() {
        String redisKey = WeChatConstants.WE_CHAT_MESSAGE_KEY_PROGRAM;
        Long size = redisUtil.getListSize(redisKey);
        logger.info("TemplateMessageServiceImpl.consumeProgram | size:" + size);
        if(size < 1){
            return;
        }
        for (int i = 0; i < size; i++) {
            //如果10秒钟拿不到一个数据，那么退出循环
            Object data = redisUtil.getRightPop(redisKey, 10L);
            if(null == data){
                continue;
            }
            try{
                TemplateMessageResponse templateMessage = JSONObject.toJavaObject(JSONObject.parseObject(data.toString()), TemplateMessageResponse.class);
                boolean result = wechatNewService.sendMiniSubscribeMessage(templateMessage);
                if(!result){
                    redisUtil.lPush(redisKey, data);
                }
            }catch (Exception e){
                redisUtil.lPush(redisKey, data);
            }
        }
    }

    /**
     * 发送公众号模板消息
     * @param templateId 模板消息编号
     * @param temMap 内容Map
     * @param openId 微信用户openId
     */
    @Override
    public void pushTemplateMessage(Integer templateId, HashMap<String, String> temMap, String openId) {
        TemplateMessageResponse templateMessageVo = new TemplateMessageResponse();

        TemplateMessage templateMessage = info(templateId);
        if(ObjectUtil.isNull(templateMessage) || StrUtil.isBlank(templateMessage.getContent())){
            return;
        }
        templateMessageVo.setTemplate_id(templateMessage.getTempId());

        HashMap<String, SendTemplateMessageItemResponse> hashMap = new HashMap<>(16);
        for (Map.Entry<String, String> entry : temMap.entrySet()){
            hashMap.put(entry.getKey(), new SendTemplateMessageItemResponse(entry.getValue()));
        }

        templateMessageVo.setData(hashMap);
        templateMessageVo.setTouser(openId);

        redisUtil.lPush(WeChatConstants.WE_CHAT_MESSAGE_KEY_PUBLIC, JSONObject.toJSONString(templateMessageVo));
    }

    /**
     * 发送小程序订阅消息
     * @param templateId 模板消息编号
     * @param temMap 内容Map
     * @param openId 微信用户openId
     */
    @Override
    public void pushMiniTemplateMessage(Integer templateId, HashMap<String, String> temMap, String openId) {
        TemplateMessage templateMessage = info(templateId);
        if(ObjectUtil.isNull(templateMessage) || StrUtil.isBlank(templateMessage.getContent())){
            return;
        }

        ProgramTemplateMessageResponse programTemplateMessageVo = new ProgramTemplateMessageResponse();
        programTemplateMessageVo.setTemplate_id(templateMessage.getTempId());

        //组装关键字数据
        HashMap<String, SendProgramTemplateMessageItemResponse> hashMap = new HashMap<>(16);
        temMap.forEach((key, value) -> hashMap.put(key, new SendProgramTemplateMessageItemResponse(value)));

        programTemplateMessageVo.setData(hashMap);
        programTemplateMessageVo.setTouser(openId);
        redisUtil.lPush(WeChatConstants.WE_CHAT_MESSAGE_KEY_PROGRAM, JSONObject.toJSONString(programTemplateMessageVo));
    }

    /**
     * 获取模板列表
     * @param tidList id数组
     * @return {@code List<TemplateMessage>}
     */
    @Override
    public List<TemplateMessage> getByIdList(List<Integer> tidList) {
        LambdaQueryWrapper<TemplateMessage> query = new LambdaQueryWrapper<>();
        query.in(TemplateMessage::getId, tidList);
        return dao.selectList(query);
    }

    /**
     * 通过模板编号获取列表
     * @param idList 模板编号列表
     * @return {@code List<TemplateMessage>}
     */
    private List<TemplateMessage> getListByIdList(List<Integer> idList) {
        LambdaQueryWrapper<TemplateMessage> query = Wrappers.lambdaQuery();
        query.in(TemplateMessage::getId, idList);
        return dao.selectList(query);
    }

    /**
     * 获取小程序订阅消息kidList
     * @param content 本地保存的内容
     * @param templateKeyVoList 小程序模板key对象数组
     * @return {@code List<Integer>}
     */
    private List<Integer> getRoutineKidList(String content, List<RoutineTemplateKeyResponse> templateKeyVoList) {
        // 分解出本地的关键词内容数组
        String replace = content.replace("\r\n", "");
        String[] split = replace.split("}}");
        List<String> collect = Stream.of(split).map(s -> {
            s = s.substring(0, s.indexOf("{"));
            return s;
        }).collect(Collectors.toList());

        Map<String, Integer> map = new HashMap<>(16);
        templateKeyVoList.forEach(e -> map.put(e.getName(), e.getKid()));

        List<Integer> kidList = new ArrayList<>();
        collect.forEach(e -> {
            if (map.containsKey(e)) {
                kidList.add(map.get(e));
            }
        });
        return kidList;
    }
}
